/*
 * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2019. All rights reserved.
 * Description: video analysis video process implementation
 * Author: HiMobileCam Reference Develop Team
 * Create: 2019-11-01
 */

#include "hi_videoprocess.h"
#include "videoprocess_queue.h"
#include "hi_mapi_vproc.h"
#include "hi_appcomm_util.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#define VIDEOPROCESS_TASK_NUM_MAX       2
#define VIDEOPROCESS_PROC_FRAME_NUM_MAX 2

typedef enum {
    VIDEOPROCESS_TASK_STATE_INVALID = 0,
    VIDEOPROCESS_TASK_STATE_STOPED,
    VIDEOPROCESS_TASK_STATE_STARTED,
    VIDEOPROCESS_TASK_STATE_PREPARE,
    VIDEOPROCESS_TASK_STATE_BUTT
} VIDEOPROCESS_TaskState;

typedef struct {
    pthread_t taskThreadCheckId;
    pthread_mutex_t taskMutex;
    pthread_mutex_t regMutex;
    HI_HANDLE taskHdl;
    HI_HANDLE queueHdl;
    HI_BOOL taskThreadProcFlag;
    VIDEOPROCESS_TaskState  taskState;
    HI_VIDEOPROCESS_TaskCfg taskCfg;
} VIDEOPROCESS_TaskCtx;

typedef struct {
    pthread_mutex_t ctxMutex;
    VIDEOPROCESS_TaskCtx taskCtx[VIDEOPROCESS_TASK_NUM_MAX];
} VIDEOPROCESS_Ctx;
static VIDEOPROCESS_Ctx g_videoProcessCtx;

static HI_BOOL g_videoProcessInitFlg = HI_FALSE;
static pthread_mutex_t g_videoProcessInitMutex = PTHREAD_MUTEX_INITIALIZER;

#define VIDEOPROCESS_RETURN_IF_NOT_INIT()                  \
    do{                                                    \
        HI_MUTEX_LOCK(g_videoProcessInitMutex);            \
        if (HI_TRUE != g_videoProcessInitFlg) {            \
            HI_MUTEX_UNLOCK(g_videoProcessInitMutex);      \
            MLOGW("not inited, please init first\n");      \
            return HI_VIDEOPROCESS_ENOTINIT; \
        }                                                  \
        HI_MUTEX_UNLOCK(g_videoProcessInitMutex);          \
    } while (0)

static HI_S32 VIDEOPROCESS_CheckCfg(const HI_VIDEOPROCESS_TaskCfg *taskCfg)
{
    if (taskCfg->algCnt > VIDEOPROCESS_TASK_NUM_MAX) {
        MLOGE("algCnt(%d) err\n", taskCfg->algCnt);
        return HI_FAILURE;
    }

    for (HI_S32 i = 0; i < taskCfg->algCnt; i++) {
        if (taskCfg->algAttr[i].algType >= HI_VIDEOPROCESS_ALG_TYPE_BUTT) {
            MLOGE("algType(%d) err\n", taskCfg->algAttr[i].algType);
            return HI_FAILURE;
        }
    }
    return HI_SUCCESS;
}

static HI_S32 VIDEOPROCESS_GetTaskHdl(VIDEOPROCESS_Ctx *videoProcessCtx, HI_HANDLE *taskHdl)
{
    HI_S32 i;
    for (i = 0; i < VIDEOPROCESS_TASK_NUM_MAX; i++) {
        if (videoProcessCtx->taskCtx[i].taskState == VIDEOPROCESS_TASK_STATE_INVALID) {
            break;
        }
    }

    if (i == VIDEOPROCESS_TASK_NUM_MAX) {
        MLOGE("task reach max number(%d)\n", VIDEOPROCESS_TASK_NUM_MAX);
        return HI_VIDEOPROCESS_EFULL;
    }

    *taskHdl = i;
    return HI_SUCCESS;
}

static HI_S32 VIDEOPROCESS_SetDumpDepth(HI_VIDEOPROCESS_TaskCfg* taskCfg, HI_U32 dumpDepth)
{
    if (taskCfg->yuvSrc.yuvMode == HI_VIDEOPROCESS_YUV_MOD_VPSS) {
        HI_MAPI_DUMP_YUV_ATTR_S dumpYUVAttr = {0};
        if (dumpDepth == 0) {
            dumpYUVAttr.bEnable = HI_FALSE;
        } else {
            dumpYUVAttr.bEnable = HI_TRUE;
        }
        dumpYUVAttr.u32Depth = dumpDepth;

        HI_S32 ret = HI_MAPI_VPROC_SetVpssDumpYUVAttr(taskCfg->yuvSrc.modHdl, taskCfg->yuvSrc.chnHdl, &dumpYUVAttr);
        if (ret != HI_SUCCESS) {
            MLOGE("HI_MAPI_VPROC_SetVpssDumpYUVAttr fail(%d)\n", ret);
            return HI_FAILURE;
        }
    } else {
        MLOGE("yuvMode(%d) not support.\n", taskCfg->yuvSrc.yuvMode);
        return HI_VIDEOPROCESS_EINVAL;
    }

    return HI_SUCCESS;
}

static HI_BOOL VIDEOPROCESS_AlgProcThreadCheck(VIDEOPROCESS_TaskCtx* taskCtx)
{
    HI_MUTEX_LOCK(taskCtx->taskMutex);
    if (taskCtx->taskState != VIDEOPROCESS_TASK_STATE_STARTED) {
        HI_MUTEX_UNLOCK(taskCtx->taskMutex);
        return HI_FALSE;
    }

    HI_MUTEX_UNLOCK(taskCtx->taskMutex);
    return HI_TRUE;
}

static HI_S32 VIDEOPROCESS_AlgProcDumpYUV(VIDEOPROCESS_TaskCtx* taskCtx)
{
    HI_HANDLE grpHdl = taskCtx->taskCfg.yuvSrc.modHdl;
    HI_HANDLE portHdl = taskCtx->taskCfg.yuvSrc.chnHdl;
    HI_HANDLE queueHdl = taskCtx->queueHdl;
    HI_MAPI_FRAME_DATA_S dumpFrameData = {0};

    HI_MUTEX_LOCK(taskCtx->taskMutex);
    HI_S32 ret = HI_MAPI_VPROC_GetPortFrame(grpHdl, portHdl, HI_FALSE, &dumpFrameData);
    if (ret != HI_SUCCESS) {
        HI_MUTEX_UNLOCK(taskCtx->taskMutex);
        MLOGE("task(%d) HI_MAPI_VPROC_GetChnFrame Failed\n", taskCtx->taskHdl);
        return HI_FAILURE;
    }

    ret = VIDEOPROCESS_PushQueue(queueHdl, &dumpFrameData);
    if (ret != HI_SUCCESS) {

        ret = HI_MAPI_VPROC_ReleasePortFrame(grpHdl, portHdl, HI_FALSE, &dumpFrameData);
        if (ret != HI_SUCCESS) {
            MLOGE("task[%d] HI_MAPI_VPROC_ReleaseChnFrame Failed\n", taskCtx->taskHdl);
            return HI_FAILURE;
        }

        HI_MUTEX_UNLOCK(taskCtx->taskMutex);
        MLOGE("task[%d] VIDEODETECT_QUEUE_Push Failed\n", taskCtx->taskHdl);
        return HI_FAILURE;
    } else {
        MLOGD(YELLOW"task[%d] Push yuv data(%d x %d), pts(%lld)"NONE"\n",
            taskCtx->taskHdl, dumpFrameData.u32Width, dumpFrameData.u32Height, dumpFrameData.u64pts);
    }

    HI_MUTEX_UNLOCK(taskCtx->taskMutex);
    return HI_SUCCESS;
}

static HI_S32 VIDEOPROCESS_AlgProcReleaseYUV(VIDEOPROCESS_TaskCtx* taskCtx)
{
    HI_HANDLE grpHdl = taskCtx->taskCfg.yuvSrc.modHdl;
    HI_HANDLE portHdl = taskCtx->taskCfg.yuvSrc.chnHdl;
    HI_HANDLE queueHdl = taskCtx->queueHdl;
    HI_BOOL popNodeSuccess = HI_FALSE;
    HI_MAPI_FRAME_DATA_S releaseFrameData = {0};

    HI_MUTEX_LOCK(taskCtx->taskMutex);
    HI_S32 ret =  VIDEOPROCESS_PopQueue(queueHdl, &releaseFrameData, &popNodeSuccess);
    if (popNodeSuccess && ret == HI_SUCCESS) {
        ret = HI_MAPI_VPROC_ReleasePortFrame(grpHdl, portHdl, HI_FALSE, &releaseFrameData);
        if (ret != HI_SUCCESS) {
            HI_MUTEX_UNLOCK(taskCtx->taskMutex);
            MLOGE("task[%d] HI_MAPI_VPROC_ReleaseChnFrame Failed\n", taskCtx->taskHdl);
            return HI_FAILURE;
        }
    }

    HI_MUTEX_UNLOCK(taskCtx->taskMutex);
    return HI_SUCCESS;
}

static HI_S32 VIDEOPROCESS_AlgProcProcess(VIDEOPROCESS_TaskCtx* taskCtx)
{
    HI_MUTEX_LOCK(taskCtx->regMutex);

    HI_BOOL readNodeSuccess = HI_FALSE;
    HI_MAPI_FRAME_DATA_S readFrameData[VIDEOPROCESS_PROC_FRAME_NUM_MAX] = {0};

    HI_S32 ret = VIDEOPROCESS_ReadQueue(taskCtx->queueHdl, taskCtx->taskCfg.bufDepth, readFrameData, &readNodeSuccess);
    if (readNodeSuccess == HI_TRUE && ret == HI_SUCCESS) {
        for (HI_S32 i = 0; i < taskCtx->taskCfg.algCnt; i++) {
            if (taskCtx->taskCfg.algAttr[i].taskCbSet.taskCb != HI_NULL) {
                MLOGD("task[%d] readFrameData(%p)\n", taskCtx->taskHdl, &readFrameData);
                taskCtx->taskCfg.algAttr[i].taskCbSet.taskCb((HI_MAPI_FRAME_DATA_S *)&readFrameData,
                    taskCtx->taskCfg.algAttr[i].taskCbSet.privData);
            }
        }
    }
    HI_MUTEX_UNLOCK(taskCtx->regMutex);

    return ret;
}

static HI_VOID* VIDEOPROCESS_AlgProcThread(HI_VOID* arg)
{
    VIDEOPROCESS_TaskCtx* taskCtx = (VIDEOPROCESS_TaskCtx*)arg;

    HI_U32 algIntervalTimeMs = 1000 * 1000 / (taskCtx->taskCfg.frameRate); /* 1000 * 1000 us */
    while (taskCtx->taskThreadProcFlag) {
        if (!VIDEOPROCESS_AlgProcThreadCheck(taskCtx)) {
            HI_usleep(algIntervalTimeMs);
            continue;
        }

        /* get frame push to queue */
        HI_S32 ret = VIDEOPROCESS_AlgProcDumpYUV(taskCtx);
        if (ret != HI_SUCCESS) {
            HI_usleep(algIntervalTimeMs);
            continue;
        }

        /* read frame and process frame */
        ret = VIDEOPROCESS_AlgProcProcess(taskCtx);
        if (ret != HI_SUCCESS) {
            MLOGD(YELLOW"VIDEOANALYSIS_VideoProcessAlgProcProcess failed(%d)"NONE"\n", ret);
        }

        /* release frame */
        ret = VIDEOPROCESS_AlgProcReleaseYUV(taskCtx);
        if (ret != HI_SUCCESS) {
            HI_usleep(algIntervalTimeMs);
            continue;
        }

        HI_usleep(algIntervalTimeMs);
    }

    return HI_NULL;
}

static HI_S32 VIDEOPROCESS_ReleaseQueueFrame(VIDEOPROCESS_TaskCtx* taskCtx,
    HI_BOOL destroyQueue)
{
    HI_MAPI_FRAME_DATA_S queueFrameData[VIDEOPROCESS_PROC_FRAME_NUM_MAX] = {0};

    HI_U32 frameCnt;
    if (destroyQueue) {
        VIDEOPROCESS_DestroyQueue(taskCtx->queueHdl, queueFrameData, &frameCnt);
    } else {
        VIDEOPROCESS_ClearQueue(taskCtx->queueHdl, queueFrameData, &frameCnt);
    }

    if ((frameCnt > 0) &&
        (taskCtx->taskCfg.yuvSrc.yuvMode == HI_VIDEOPROCESS_YUV_MOD_VPSS)) {
        for (HI_S32 i = 0; i < frameCnt; i++) {
            HI_S32 ret = HI_MAPI_VPROC_ReleasePortFrame(taskCtx->taskCfg.yuvSrc.modHdl,
                taskCtx->taskCfg.yuvSrc.chnHdl, HI_FALSE, &queueFrameData[i]);
            if (ret != HI_SUCCESS) {
                MLOGE("HI_MAPI_VPROC_ReleaseChnFrame failed\n");
                return HI_VIDEOPROCESS_EOTHER;
            }
        }
    }
    return HI_SUCCESS;
}

static HI_S32 VIDEOANALYSIS_VideoProcessDumpVportYuv(HI_HANDLE taskHdl)
{
    HI_VIDEOPROCESS_YuvSrc *yuvSrc = &g_videoProcessCtx.taskCtx[taskHdl].taskCfg.yuvSrc;

    HI_MAPI_DUMP_YUV_ATTR_S dumpYuvAttr;
    dumpYuvAttr.bEnable = HI_TRUE;
    dumpYuvAttr.u32Depth = yuvSrc->dumpDepth;

    HI_S32 ret = HI_MAPI_VPROC_SetVpssDumpYUVAttr(yuvSrc->modHdl, yuvSrc->chnHdl, &dumpYuvAttr);
    HI_APPCOMM_CHECK_EXPR_WITHOUT_RETURN((ret == HI_SUCCESS), "SetVpssDumpYUVAttr");

    return HI_SUCCESS;
}

/* functions */
HI_S32 HI_VIDEOPROCESS_Init(HI_VOID)
{
    HI_MUTEX_LOCK(g_videoProcessInitMutex);
    if (g_videoProcessInitFlg) {
        HI_MUTEX_UNLOCK(g_videoProcessInitMutex);
        MLOGE("already inited!\n");
        return HI_VIDEOPROCESS_EINITIALIZED;
    }

    HI_MUTEX_INIT_LOCK(g_videoProcessCtx.ctxMutex);
    for (HI_S32 i = 0; i < VIDEOPROCESS_TASK_NUM_MAX; i++) {
        memset(&g_videoProcessCtx.taskCtx[i], 0x0, sizeof(VIDEOPROCESS_TaskCtx));
        HI_MUTEX_INIT_LOCK(g_videoProcessCtx.taskCtx[i].taskMutex);
        HI_MUTEX_INIT_LOCK(g_videoProcessCtx.taskCtx[i].regMutex);
        g_videoProcessCtx.taskCtx[i].taskThreadCheckId = -1;
        for (HI_S32 j = 0; j < HI_VIDEOPROCESS_TASK_ALG_NUM_MAX; j++) {
            g_videoProcessCtx.taskCtx[i].taskCfg.algAttr[j].algType = HI_VIDEOPROCESS_ALG_TYPE_BUTT;
        }
        g_videoProcessCtx.taskCtx[i].taskState = VIDEOPROCESS_TASK_STATE_INVALID;
    }

    g_videoProcessInitFlg = HI_TRUE;
    HI_MUTEX_UNLOCK(g_videoProcessInitMutex);

    return HI_SUCCESS;
}

HI_S32 HI_VIDEOPROCESS_CreateTask(const HI_VIDEOPROCESS_TaskCfg *taskCfg, HI_HANDLE *taskHdl)
{
    VIDEOPROCESS_RETURN_IF_NOT_INIT();
    HI_APPCOMM_CHECK_POINTER(taskHdl, HI_VIDEOPROCESS_EINVAL);
    HI_APPCOMM_CHECK_POINTER(taskCfg, HI_VIDEOPROCESS_EINVAL);

    if (VIDEOPROCESS_CheckCfg(taskCfg) != HI_SUCCESS) {
        return HI_VIDEOPROCESS_EINVAL;
    }

    HI_MUTEX_LOCK(g_videoProcessCtx.ctxMutex);
    HI_S32 ret = VIDEOPROCESS_GetTaskHdl(&g_videoProcessCtx, taskHdl);
    if (ret != HI_SUCCESS) {
        HI_MUTEX_UNLOCK(g_videoProcessCtx.ctxMutex);
        return ret;
    }

    g_videoProcessCtx.taskCtx[*taskHdl].taskHdl = *taskHdl;
    memcpy(&(g_videoProcessCtx.taskCtx[*taskHdl].taskCfg), taskCfg, sizeof(HI_VIDEOPROCESS_TaskCfg));
    MLOGD("taskHdl is %d\n", *taskHdl);

    ret = VIDEOPROCESS_SetDumpDepth(&(g_videoProcessCtx.taskCtx[*taskHdl].taskCfg),
        g_videoProcessCtx.taskCtx[*taskHdl].taskCfg.yuvSrc.dumpDepth);
    if (ret != HI_SUCCESS) {
        HI_MUTEX_UNLOCK(g_videoProcessCtx.ctxMutex);
        return ret;
    }

    g_videoProcessCtx.taskCtx[*taskHdl].queueHdl = VIDEOPROCESS_CreateQueue(sizeof(HI_MAPI_FRAME_DATA_S),
        taskCfg->bufDepth);
    if (g_videoProcessCtx.taskCtx[*taskHdl].queueHdl == 0) {
        HI_MUTEX_UNLOCK(g_videoProcessCtx.ctxMutex);
        MLOGE("create queue fail\n");
        return HI_FAILURE;
    }

    ret = pthread_create(&(g_videoProcessCtx.taskCtx[*taskHdl].taskThreadCheckId),
        HI_NULL, VIDEOPROCESS_AlgProcThread, &(g_videoProcessCtx.taskCtx[*taskHdl]));
    if (ret != HI_SUCCESS) {
        HI_MUTEX_UNLOCK(g_videoProcessCtx.ctxMutex);
        MLOGE("create alg proc thread failed!\n");
        return HI_VIDEOPROCESS_EOTHER;
    }

    g_videoProcessCtx.taskCtx[*taskHdl].taskState = VIDEOPROCESS_TASK_STATE_PREPARE;
    g_videoProcessCtx.taskCtx[*taskHdl].taskThreadProcFlag = HI_TRUE;

    HI_MUTEX_UNLOCK(g_videoProcessCtx.ctxMutex);
    return HI_SUCCESS;
}

HI_S32 HI_VIDEOPROCESS_StartTask(HI_HANDLE taskHdl)
{
    VIDEOPROCESS_RETURN_IF_NOT_INIT();
    HI_MUTEX_LOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);
    MLOGD("taskHdl(%d) taskState(%d)\n", taskHdl, g_videoProcessCtx.taskCtx[taskHdl].taskState);
    if (g_videoProcessCtx.taskCtx[taskHdl].taskState ==  VIDEOPROCESS_TASK_STATE_INVALID) {
        MLOGE("not created\n");
        HI_MUTEX_UNLOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);
        return HI_VIDEOPROCESS_EOTHER;
    }

    if (g_videoProcessCtx.taskCtx[taskHdl].taskState ==  VIDEOPROCESS_TASK_STATE_STARTED) {
        MLOGD("already started\n");
        HI_MUTEX_UNLOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);
        return HI_VIDEOPROCESS_EOTHER;
    }

    if (g_videoProcessCtx.taskCtx[taskHdl].taskCfg.yuvSrc.yuvMode == HI_VIDEOPROCESS_YUV_MOD_VPSS) {
        HI_S32 ret = VIDEOANALYSIS_VideoProcessDumpVportYuv(taskHdl);
        if (ret != HI_SUCCESS) {
            MLOGE("dump vport yuv failed\n");
            HI_MUTEX_UNLOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);
            return HI_VIDEOPROCESS_EOTHER;
        }
    }

    g_videoProcessCtx.taskCtx[taskHdl].taskState = VIDEOPROCESS_TASK_STATE_STARTED;
    HI_MUTEX_UNLOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);

    return HI_SUCCESS;
}

HI_S32 HI_VIDEOPROCESS_StopTask(HI_HANDLE taskHdl)
{
    VIDEOPROCESS_RETURN_IF_NOT_INIT();
    HI_MUTEX_LOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);
    if (g_videoProcessCtx.taskCtx[taskHdl].taskState == VIDEOPROCESS_TASK_STATE_INVALID) {
        MLOGE("not created.\n");
        HI_MUTEX_UNLOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);
        return HI_VIDEOPROCESS_EOTHER;
    }

    if ((g_videoProcessCtx.taskCtx[taskHdl].taskState == VIDEOPROCESS_TASK_STATE_STOPED) ||
        (g_videoProcessCtx.taskCtx[taskHdl].taskState != VIDEOPROCESS_TASK_STATE_STARTED)) {
        MLOGD("already stoped or not start\n");
        HI_MUTEX_UNLOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);
        return HI_VIDEOPROCESS_EOTHER;
    }

    HI_S32 ret = VIDEOPROCESS_ReleaseQueueFrame(&(g_videoProcessCtx.taskCtx[taskHdl]), HI_FALSE);
    if (ret != HI_SUCCESS) {
        MLOGE("VIDEODETECT_ReleaseQueueFrame Fail!\n");
        HI_MUTEX_UNLOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);
        return HI_VIDEOPROCESS_EOTHER;
    }

    g_videoProcessCtx.taskCtx[taskHdl].taskState = VIDEOPROCESS_TASK_STATE_STOPED;
    HI_MUTEX_UNLOCK(g_videoProcessCtx.taskCtx[taskHdl].taskMutex);

    return HI_SUCCESS;
}

HI_S32 HI_VIDEOPROCESS_DestroyTask(HI_HANDLE taskHdl)
{
    VIDEOPROCESS_RETURN_IF_NOT_INIT();
    VIDEOPROCESS_Ctx* videoProcessCtx = &g_videoProcessCtx;

    if (videoProcessCtx->taskCtx[taskHdl].taskState == VIDEOPROCESS_TASK_STATE_INVALID) {
        MLOGE("not created\n");;
        return HI_VIDEOPROCESS_EOTHER;
    }

    HI_MUTEX_LOCK(videoProcessCtx->ctxMutex);
    videoProcessCtx->taskCtx[taskHdl].taskThreadProcFlag = HI_FALSE;
    HI_S32 ret = pthread_join(videoProcessCtx->taskCtx[taskHdl].taskThreadCheckId, HI_NULL);
    if (ret != HI_SUCCESS) {
        MLOGE("join task thread failed\n");
        HI_MUTEX_UNLOCK(videoProcessCtx->ctxMutex);
        return HI_VIDEOPROCESS_EOTHER;
    }

    ret = VIDEOPROCESS_ReleaseQueueFrame(&(videoProcessCtx->taskCtx[taskHdl]), HI_TRUE);
    if (ret != HI_SUCCESS) {
        MLOGE("VIDEODETECT_ReleaseQueueFrame failed\n");
        HI_MUTEX_UNLOCK(videoProcessCtx->ctxMutex);
        return HI_VIDEOPROCESS_EOTHER;
    }

    ret = VIDEOPROCESS_SetDumpDepth(&(videoProcessCtx->taskCtx[taskHdl].taskCfg), 0);
    if (ret != HI_SUCCESS) {
        MLOGE("VIDEODETECT_SetDumpDepth failed\n");
        HI_MUTEX_UNLOCK(videoProcessCtx->ctxMutex);
        return HI_VIDEOPROCESS_EOTHER;
    }

    for (HI_S32 i = 0; i < HI_VIDEOPROCESS_TASK_ALG_NUM_MAX; i++) {
        videoProcessCtx->taskCtx[taskHdl].taskCfg.algAttr[i].algType = HI_VIDEOPROCESS_ALG_TYPE_BUTT;
        videoProcessCtx->taskCtx[taskHdl].taskCfg.algAttr[i].taskCbSet.taskCb = HI_NULL;
        videoProcessCtx->taskCtx[taskHdl].taskCfg.algAttr[i].taskCbSet.privData = HI_NULL;
    }

    videoProcessCtx->taskCtx[taskHdl].taskCfg.frameRate = 0;
    videoProcessCtx->taskCtx[taskHdl].taskCfg.bufDepth = 0;
    videoProcessCtx->taskCtx[taskHdl].taskCfg.algCnt = 0;
    videoProcessCtx->taskCtx[taskHdl].taskState = VIDEOPROCESS_TASK_STATE_INVALID;
    HI_MUTEX_UNLOCK(videoProcessCtx->ctxMutex);
    return HI_SUCCESS;
}

HI_S32 HI_VIDEOPROCESS_Deinit(HI_VOID)
{
    VIDEOPROCESS_RETURN_IF_NOT_INIT();

    HI_MUTEX_LOCK(g_videoProcessInitMutex);
    VIDEOPROCESS_Ctx* videoProcessCtx = &g_videoProcessCtx;

    for (HI_S32 i = 0; i < VIDEOPROCESS_TASK_NUM_MAX; i++) {
        if (videoProcessCtx->taskCtx[i].taskState != VIDEOPROCESS_TASK_STATE_INVALID) {
            /* just for debuging, not return error */
            MLOGE("task %d is not destroy\n", i);
        }
        HI_MUTEX_DESTROY(videoProcessCtx->taskCtx[i].taskMutex);
        HI_MUTEX_DESTROY(videoProcessCtx->taskCtx[i].regMutex);
        memset(&(videoProcessCtx->taskCtx[i]), 0, sizeof(VIDEOPROCESS_TaskCtx));
    }

    HI_MUTEX_DESTROY(videoProcessCtx->ctxMutex);
    g_videoProcessInitFlg = HI_FALSE;
    HI_MUTEX_UNLOCK(g_videoProcessInitMutex);

    return HI_SUCCESS;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */
